package com.nl.lib_project.moshi

import com.squareup.moshi.*
import com.squareup.moshi.JsonAdapter.Factory
import java.io.IOException
import java.lang.reflect.Type

/** 作者: wangfei 创建时间: 2022/1/13 包名: com.nl.lib_project.moshi 类名: HashMapJsonAdapter */
class LinkHashMapJsonAdapter<K, V>(moshi: Moshi, keyType: Type?, valueType: Type?) :
    JsonAdapter<LinkedHashMap<K?, V?>?>() {

  companion object {
    val FACTORY = Factory { type, annotations, moshi ->
      if (annotations.isNotEmpty()) return@Factory null
      val rawType = Types.getRawType(type)
      if (rawType != LinkedHashMap::class.java) return@Factory null
      val keyAndValue =
          if (type === java.util.Properties::class.java)
              arrayOf<Type>(String::class.java, String::class.java)
          else {
            arrayOf<Type>(Any::class.java, Any::class.java)
          }
      LinkHashMapJsonAdapter<Any?, Any>(moshi, keyAndValue[0], keyAndValue[1]).nullSafe()
    }
  }

  private var keyAdapter: JsonAdapter<K>? = null
  private var valueAdapter: JsonAdapter<V>? = null

  @Throws(IOException::class)
  override fun toJson(writer: JsonWriter, value: LinkedHashMap<K?, V?>?) {
    writer.beginObject()
    for ((key, value) in value!!.entries) {
      if (key == null) {
        throw JsonDataException("Map key is null at " + writer.path)
      }
      writer.promoteValueToName()
      keyAdapter!!.toJson(writer, key)
      valueAdapter!!.toJson(writer, value)
    }
    writer.endObject()
  }

  @Throws(IOException::class)
  override fun fromJson(reader: JsonReader): LinkedHashMap<K?, V?>? {
    val result = LinkedHashMap<K?, V?>()
    reader.beginObject()
    while (reader.hasNext()) {
      reader.promoteNameToValue()
      val name = keyAdapter!!.fromJson(reader)
      val value = valueAdapter!!.fromJson(reader)
      val replaced = result.put(name, value)
      if (replaced != null) {
        throw JsonDataException(
            "Map key '" +
                name +
                "' has multiple values at path " +
                reader.path +
                ": " +
                replaced +
                " and " +
                value)
      }
    }
    reader.endObject()
    return result
  }

  override fun toString(): String {
    return "JsonAdapter($keyAdapter=$valueAdapter)"
  }
}
